package com.macro.mall.portal.util;

import org.springframework.beans.factory.annotation.Autowired;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;

public class ShareCodeUtils {


    private static final int offset = 24;
    private static final String stopChar = "Z";
    private static final int minCodeLen = 5;

    @Autowired
    private RedisTool redisTool;

    private static final Map<Integer, String> codeMap = new HashMap<Integer, String>() {
        private static final long serialVersionUID = 8079608538849685645L;

        {
            put(0, "A");
            put(1, "B");
            put(2, "C");
            put(3, "D");
            put(4, "E");
            put(5, "F");
            put(6, "G");
            put(7, "H");
            put(8, "I");
            put(9, "J");
            put(10, "K");
            put(11, "L");
            put(12, "M");
            put(13, "N");
            put(14, "P");
            put(15, "Q");
            put(16, "R");
            put(17, "S");
            put(18, "T");
            put(19, "U");
            put(20, "V");
            put(21, "W");
            put(22, "X");
            put(23, "Y");
        }
    };

    private static final Map<String, Integer> intMap = new HashMap<String, Integer>() {

        private static final long serialVersionUID = -2155582790030838660L;

        {
            put("A", 0);
            put("B", 1);
            put("C", 2);
            put("D", 3);
            put("E", 4);
            put("F", 5);
            put("G", 6);
            put("H", 7);
            put("I", 8);
            put("J", 9);
            put("K", 10);
            put("L", 11);
            put("M", 12);
            put("N", 13);
            put("P", 14);
            put("Q", 15);
            put("R", 16);
            put("S", 17);
            put("T", 18);
            put("U", 19);
            put("V", 20);
            put("W", 21);
            put("X", 22);
            put("Y", 23);
        }
    };

    /**
     * 根据 id 生成邀请码 6 位
     * 如果是 6 位的邀请码只能支持 191102976 1亿9千万用户
     *
     * @param id 用户id
     * @return 邀请码
     */
    public static String createCode(int id) {

        String code = int2chars(id);
        if (code.length() < (minCodeLen - 1)) {
            code = code + stopChar + codeTail(code);
        } else if (code.length() < minCodeLen) {
            code = code + stopChar;
        }
        return code;
    }

    /**
     * 从邀请获取用户 id
     *
     * @param code 邀请码
     * @return 用户id
     */
    public static int codeRecover(String code) {
        int len = code.indexOf(stopChar);
        if (len > 0) {
            code = code.substring(0, len);
        }
        return chars2int(code);
    }

    private static String codeTail(String code) {
        StringBuilder res = new StringBuilder();
        String lastChar = code.substring(code.length() - 1);// 原code的尾数
        for (int i = 0; i < (minCodeLen - 1 - code.length()); i++) {
            res.append(lastChar);
        }
        return res.toString();
    }


    private static String int2chars(int id) {
        int div = id / offset;
        int remainder = id % offset;

        if (div == 0) {
            return codeMap.get(id);
        } else if (div < offset) {
            return codeMap.get(div) + codeMap.get(remainder);
        } else {
            return int2chars(div) + codeMap.get(remainder);
        }
    }

    private static int chars2int(String chats) {
        int res = 0;
        int codeLen = chats.length();
        for (int i = 0; i < codeLen; i++) {
            String a = chats.substring(i, i + 1);
            if (intMap.containsKey(a)) {
                res += intMap.get(a) * (Math.pow(offset, (codeLen - i - 1)));
            } else {
                res = 0;
                break;
            }
        }
        return res;
    }


    /**
     * 自定义进制(0,1没有加入,容易与o,l混淆)
     */
    private static final char[] r = new char[]{'Q', 'W', 'E', '8', 'A', 'S', '2', 'D', 'Z', 'X', '9', 'C', '7', 'P', '5', 'I', 'K', '3', 'M', 'J', 'U', 'F', 'R', '4', 'V', 'Y', 'L', 'T', 'N', '6', 'B', 'G', 'H'};

    /**
     * (不能与自定义进制有重复)
     */
    private static final char b = 'O';

    /**
     * 进制长度
     */
    private static final int binLen = r.length;

    /**
     * 序列最小长度
     */
    private static final int s = 6;

    /**
     * 根据ID生成六位随机码
     *
     * @param id ID
     * @return 随机码
     */
    public static String randomSerialCode(int id) {
        char[] buf = new char[32];
        int charPos = 32;

        while ((id / binLen) > 0) {
            int ind = (int) (id % binLen);
            // System.out.println(num + "-->" + ind);
            buf[--charPos] = r[ind];
            id /= binLen;
        }
        buf[--charPos] = r[(int) (id % binLen)];
        // System.out.println(num + "-->" + num % binLen);
        String str = new String(buf, charPos, (32 - charPos));
        // 不够长度的自动随机补全
        if (str.length() < s) {
            StringBuilder sb = new StringBuilder();
            sb.append(b);
            Random rnd = new Random();
            for (int i = 1; i < s - str.length(); i++) {
                sb.append(r[rnd.nextInt(binLen)]);
            }
            str += sb.toString();
        }
        return str;
    }

    public static int randomCodeToId(String code) {
        char[] chs = code.toCharArray();
        int res = 0;
        for (int i = 0; i < chs.length; i++) {
            int ind = 0;
            for (int j = 0; j < binLen; j++) {
                if (chs[i] == r[j]) {
                    ind = j;
                    break;
                }
            }
            if (chs[i] == b) {
                break;
            }
            if (i > 0) {
                res = res * binLen + ind;
            } else {
                res = ind;
            }
            // System.out.println(ind + "-->" + res);
        }
        return res;
    }
}
